using UnityEngine;
using System.Collections;
using DanielSig.UnityExtensions;
using DanielSig;

public class Gun : MonoBehaviour, ISensor
{
	public Rect DisplayRect;
	public TextAnchor DisplayAnchor;
	public Color DisplayColor = Color.green;
	public Color BackColor = Color.black;
	
	public GameObject ProjectilePrefab;
	public GameObject ProjectileHitListener;
	public string ProjectileTag;
	public int ReloadTime;
	public int AmmoCount;
	public int MaxAmmo;
	
	public bool UserInputOverride;
	public Material LaserMaterial;
	public Color LaserColor;
	public Color LaserLockColor;
	public float LaserWidth;
	public float LaserLockWidth;
	
	private int _reloadCountdown = 0;
	private Texture2D _tex;
	private Texture2D _back;
	private float[] _arrayCache = new float[1];
	
	void Awake()
	{
		_tex = new Texture2D(1,1);
		_tex.SetPixel(0,0,DisplayColor);
		_tex.Apply();
		
		_back = new Texture2D(1,1);
		_back.SetPixel(0,0,BackColor);
		_back.Apply();
	}
	
	void ShootProjectile()
	{
		if(_reloadCountdown == 0 && AmmoCount > 0)
		{
			AmmoCount--;
			Quaternion rotation = transform.rotation;
			Vector3 offset = transform.position - transform.parent.position;
			if(UserInputOverride)
			{
				if(!Camera.main.isOrthoGraphic)
					rotation = Quaternion.Euler(new Vector3(0, Camera.main.transform.eulerAngles.y, 0));
				else
				{
					Vector3 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
					Plane plane = new Plane(Vector3.up, Vector3.zero);
					target = plane.CutLine(target, target + Camera.main.transform.forward * 200F);
					
					rotation = Quaternion.FromToRotation(Vector3.forward, transform.parent.position.DirectionTowards(target));
				}
				offset = rotation * Vector3.forward;
			}
			GameObject projectile = Instantiate(ProjectilePrefab, transform.parent.position + offset, rotation) as GameObject;
			projectile.tag = ProjectileTag;
			ProjectileController ctrl = projectile.GetComponent<ProjectileController>();
			ctrl.CollisionMask.value &= ~(1 << gameObject.layer);
			ctrl.Shooter = ProjectileHitListener;
			
			_reloadCountdown = ReloadTime;
		}
	}
	void OnDestroy()
	{
		foreach(GameObject spawn in GameObject.FindGameObjectsWithTag(ProjectileTag))
		{
			Destroy(spawn);
		}
	}

	void AddAmmo(int amount)
	{
		if(amount < 0)
			amount = 0;
		
		AmmoCount += amount;
		
		if(AmmoCount > MaxAmmo)
			AmmoCount = MaxAmmo;
	}
	
	public void UpdateSensors()
	{
		if(_reloadCountdown > 0)
			_reloadCountdown--;
		_arrayCache[0] = AmmoCount;
	}
	
	void OnGUI()
	{
		Graphics.DrawTexture(DisplayRect.InScreenPixels(DisplayAnchor), _back);
		Graphics.DrawTexture(DisplayRect.ScaleSize(AmmoCount / (float)MaxAmmo, 1F).InScreenPixels(DisplayAnchor), _tex);
	}
	void Update()
	{
		if(UserInputOverride && Camera.main.isOrthoGraphic)
		{
			Vector3 center = transform.parent.position;
			Vector3 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
			Plane plane = new Plane(Vector3.up, Vector3.zero);
			target = plane.CutLine(target, target + Camera.main.transform.forward * 200F);
			
			Ray ray = new Ray(center, center.DirectionTowards(target));
			
			RaycastHit hit = ray.GetHit();
			target = hit.point;
			bool enemyLock = hit.transform.Request<SensationType>("Observation", SensationType.None) == SensationType.Enemy;
			Color color = enemyLock ? LaserLockColor : LaserColor;
			float width = enemyLock ? LaserLockWidth : LaserWidth;
			
			LineRenderer line = this.RequestComponent<LineRenderer>();
			line.sharedMaterial = LaserMaterial;
			line.SetVertexCount(2);
			line.SetPosition(0,center + ray.direction * 0.5F);
			line.SetPosition(1,target);
			line.SetColors(color, color);
			line.SetWidth(width, width);
			//Debug.DrawLine(center + ray.direction * 0.5F, target, color);
		}
	}

	#region ISensor implementation
	public bool HasFixedDirection{ get{ return false; } }
	public SensationType Type { get{ return SensationType.MyAmmo; } }

	public float[] Values
	{
		get
		{
			return _arrayCache;
		}
	}
	#endregion
}

